home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Orlando_1993 / Devcon93.4 / CAMD / examples / trans / trans.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-01  |  17.0 KB  |  681 lines

  1.  
  2. #include <exec/types.h>
  3. #include <exec/lists.h>
  4. #include <exec/memory.h>
  5. #include <intuition/intuition.h>
  6. #include <intuition/classes.h>
  7. #include <dos/dos.h>
  8. #include <midi/realtime.h>
  9.  
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <stddef.h>
  13.  
  14. #include "trans.h"
  15. #include "trans_rev.h"
  16.  
  17. #include <clib/exec_protos.h>
  18. #include <clib/graphics_protos.h>
  19. #include <clib/intuition_protos.h>
  20. #include <clib/gadtools_protos.h>
  21. #include <clib/utility_protos.h>
  22. #include <clib/realtime_protos.h>
  23. #include <clib/alib_protos.h>
  24. #include <clib/macros.h>
  25.  
  26. #include <pragmas/exec_pragmas.h>
  27. #include <pragmas/graphics_pragmas.h>
  28. #include <pragmas/intuition_pragmas.h>
  29. #include <pragmas/gadtools_pragmas.h>
  30. #include <pragmas/utility_pragmas.h>
  31. #include <pragmas/realtime_pragmas.h>
  32.  
  33. char vers[] = VERSTAG;
  34. struct Library *IntuitionBase;
  35. struct Library *GadToolsBase;
  36. struct Library *GfxBase;
  37. struct Library *UtilityBase,
  38.                 *RealTimeBase;
  39.  
  40. struct IntuiText BodyText = {0,1,JAM2,20,8,NULL,(UBYTE *)TEXT_NORELEASE2,NULL};
  41. struct IntuiText NegText  = {0,1,JAM2, 6,4,NULL,(UBYTE *)TEXT_OK,NULL};
  42.  
  43.     /* declarations for box image class */
  44.  
  45. Class                    *box_class;
  46. Class *initBoxClass(void);
  47. void freeBoxClass(Class *);
  48.  
  49. extern struct TextFont digitsFont;
  50.  
  51. LONG                    current_time;
  52. WORD                    clock_state = CLOCKSTATE_STOPPED;
  53. struct Task                *main_task;
  54.  
  55. WORD                    selected_digit = -1;
  56.  
  57. WORD                    drag_state,
  58.                         drag_delay,
  59.                         drag_accum;
  60.  
  61. struct Gadget            *last_gadget;
  62.  
  63. struct PlayerInfo        *control_player;
  64.  
  65.     /* prototypes for tag functions */
  66.  
  67. struct PlayerInfo *CreatePlayer(Tag tag, ...)
  68. {    return CreatePlayerA((struct TagItem *)&tag );
  69. }
  70.  
  71. BOOL SetPlayerAttrs(struct PlayerInfo *pi, Tag tag, ...)
  72. {    return SetPlayerAttrsA(pi, (struct TagItem *)&tag );
  73. }
  74.  
  75. ULONG __asm __interrupt __saveds myHookFunc (
  76.     register __a1 struct pmTime        *msg,
  77.     register __a2 struct PlayerInfo *pi );
  78.  
  79. struct Hook myHook = {
  80.     { NULL, NULL },
  81.     myHookFunc,
  82. };
  83.  
  84. VOID main(int argc, char **argv)
  85.   {
  86.   struct TMData *TMData;
  87.   ULONG error;
  88.  
  89.   main_task = FindTask(0);
  90.  
  91.   if(!(IntuitionBase = OpenLibrary((UBYTE *)"intuition.library", 37L)))
  92.     {
  93.     if(IntuitionBase = OpenLibrary((UBYTE *)"intuition.library", 0L))
  94.       {
  95.       AutoRequest(NULL, &BodyText, NULL, &NegText, 0, 0, 320, 80);
  96.       CloseLibrary(IntuitionBase);
  97.       }
  98.     cleanexit(NULL, RETURN_FAIL);
  99.     }
  100.  
  101.   if(!(GadToolsBase = OpenLibrary((UBYTE *)"gadtools.library", 37L)))
  102.     {
  103.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOLIBRARY, (UBYTE *)TEXT_ABORT, NULL, "gadtools.library V37");
  104.     cleanexit(NULL, RETURN_FAIL);
  105.     }
  106.  
  107.   if(!(UtilityBase = OpenLibrary((UBYTE *)"utility.library", 37L)))
  108.     {
  109.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOLIBRARY, (UBYTE *)TEXT_ABORT, NULL, "utility.library V37");
  110.     cleanexit(NULL, RETURN_FAIL);
  111.     }
  112.  
  113.   if(!(GfxBase = OpenLibrary((UBYTE *)"graphics.library", 37L)))
  114.     {
  115.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOLIBRARY, (UBYTE *)TEXT_ABORT, NULL, "graphics.library V37");
  116.     cleanexit(NULL, RETURN_FAIL);
  117.     }
  118.  
  119.   if(!(RealTimeBase = OpenLibrary((UBYTE *)"realtime.library", 0L)))
  120.     {
  121.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOLIBRARY, (UBYTE *)TEXT_ABORT, NULL, "realtime.library");
  122.     cleanexit(NULL, RETURN_FAIL);
  123.     }
  124.  
  125.   if (!(box_class = initBoxClass()))
  126.     {
  127.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOMEMORY, (UBYTE *)TEXT_ABORT, NULL, NULL);
  128.     cleanexit(NULL, RETURN_FAIL);
  129.     }
  130.  
  131.   control_player = CreatePlayer(
  132.       PLAYER_Name, "Controls",
  133.       PLAYER_Conductor, "Main",
  134.       PLAYER_Hook, &myHook,
  135.       TAG_DONE );
  136.  
  137.   if (!(control_player))
  138.     {
  139.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOPLAYER, (UBYTE *)TEXT_ABORT, NULL, NULL);
  140.     cleanexit(NULL, RETURN_FAIL);
  141.     }
  142.  
  143.   if(!(TMData = TM_Open(&error)))
  144.     {
  145.     switch(error)
  146.       {
  147.       case TMERR_MEMORY:
  148.         TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOMEMORY, (UBYTE *)TEXT_ABORT, NULL, NULL);
  149.         break;
  150.       case TMERR_MSGPORT:
  151.         TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOMSGPORT, (UBYTE *)TEXT_ABORT, NULL, NULL);
  152.         break;
  153.       }
  154.     cleanexit(NULL, RETURN_FAIL);
  155.     }
  156.  
  157.     NewList( &CDTList );
  158.  
  159.   if(!(OpenScreen_Workbench(TMData)))
  160.     {
  161.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOSCREEN, (UBYTE *)TEXT_ABORT, NULL, NULL);
  162.     cleanexit(TMData, RETURN_FAIL);
  163.     }
  164.  
  165.   if(!(OpenWindow_TRANSP(TMData)))
  166.     {
  167.     TM_Request(NULL, (UBYTE *)TEXT_ERROR, (UBYTE *)TEXT_NOWINDOW, (UBYTE *)TEXT_ABORT, NULL, NULL);
  168.     cleanexit(TMData, RETURN_FAIL);
  169.     }
  170.  
  171. /*  StopState(TMData); */
  172.         /* Act as if we just had a state change, so that we can set the clock */
  173.  
  174.     HandleSignal( TMData, SIGBREAKF_CTRL_E );
  175.  
  176.   TM_EventLoop(TMData);
  177.  
  178.   cleanexit(TMData, RETURN_OK);
  179.   }
  180.  
  181. VOID cleanexit(struct TMData *TMData, int returnvalue)
  182.   {
  183.   StripFont(&digitsFont);                        /* because of my weird font        */
  184.   if (control_player) DeletePlayer(control_player);
  185.   if (box_class) freeBoxClass(box_class);        /* delete BOOPSI image class    */
  186.  
  187.   if(TMData)
  188.     {
  189.     CloseWindow_TRANSP(TMData);
  190.     CloseWindow_SELECTCO(TMData);
  191.     CloseScreen_Workbench(TMData);
  192.     TM_Close(TMData);
  193.     }
  194.  
  195.   if(RealTimeBase)  CloseLibrary(RealTimeBase);
  196.   if(GfxBase)       CloseLibrary(GfxBase);
  197.   if(UtilityBase)   CloseLibrary(UtilityBase);
  198.   if(GadToolsBase)  CloseLibrary(GadToolsBase);
  199.   if(IntuitionBase) CloseLibrary(IntuitionBase);
  200.  
  201.   exit(returnvalue);
  202.   }
  203.  
  204. BOOL Window_TRANSP_CLOSEWINDOW(struct TMData *TMData, struct IntuiMessage *imsg)
  205.   {
  206.   last_gadget = NULL;
  207.   return(TRUE);
  208.   }
  209.  
  210. BOOL Window_TRANSP_MENUPICK(struct TMData *TMData, struct IntuiMessage *imsg)
  211.   {
  212.   UWORD menucode;
  213.   struct MenuItem *menuitem;
  214.   TMOBJECTDATA *tmobjectdata;
  215.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  216.   last_gadget = NULL;
  217.  
  218.   menucode = imsg->Code;
  219.   while(menucode != MENUNULL)
  220.     {
  221.     menuitem = ItemAddress(WindowInfo_TRANSP.Menu, menucode);
  222.     tmobjectdata = (TMOBJECTDATA *)(GTMENUITEM_USERDATA(menuitem));
  223.     eventfunc = tmobjectdata->EventFunc;
  224.  
  225.     TMData->checked_menu = menuitem->Flags & CHECKED;
  226.  
  227.     if(eventfunc)
  228.       {
  229.       if((*eventfunc)(TMData, imsg, tmobjectdata)) return(TRUE);
  230.       }
  231.  
  232.     menucode = menuitem->NextSelect;
  233.     }
  234.   return(FALSE);
  235.   }
  236.  
  237. BOOL Window_TRANSP_GADGETDOWN(struct TMData *TMData, struct IntuiMessage *imsg)
  238.   {
  239.   struct Gadget *gadget;
  240.   TMOBJECTDATA *tmobjectdata;
  241.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  242.  
  243.   last_gadget =  gadget = (struct Gadget *)imsg->IAddress;
  244.   tmobjectdata = (TMOBJECTDATA *)(gadget->UserData);
  245.   eventfunc = tmobjectdata->EventFunc;
  246.  
  247.   if(eventfunc)
  248.     {
  249.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  250.     }
  251.   return(FALSE);
  252.   }
  253.  
  254. BOOL Window_TRANSP_GADGETUP(struct TMData *TMData, struct IntuiMessage *imsg)
  255.   {
  256.   struct Gadget *gadget;
  257.   TMOBJECTDATA *tmobjectdata;
  258.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  259.  
  260.   gadget = (struct Gadget *)imsg->IAddress;
  261.   tmobjectdata = (TMOBJECTDATA *)(gadget->UserData);
  262.   eventfunc = tmobjectdata->EventFunc;
  263.   last_gadget = NULL;
  264.  
  265.     drag_state = DRAG_NONE;
  266.  
  267.   if(eventfunc)
  268.     {
  269.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  270.     }
  271.   return(FALSE);
  272.   }
  273.  
  274. BOOL Window_TRANSP_MOUSEMOVE(struct TMData *TMData, struct IntuiMessage *imsg)
  275.   {
  276. #if 0
  277.   struct Gadget *gadget;
  278.   TMOBJECTDATA *tmobjectdata;
  279.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  280.  
  281.   gadget = (struct Gadget *)imsg->IAddress;
  282.   tmobjectdata = (TMOBJECTDATA *)(gadget->UserData);
  283.   eventfunc = tmobjectdata->EventFunc;
  284.   last_gadget = NULL;
  285. #endif
  286.  
  287.     if (drag_state == DRAG_DIGIT && selected_digit >= 0)
  288.     {    LONG    scale[] = {    3600*600*10, 3600*600, 60*600*10, 60*600, 10*600, 600, (600*10)/30, 600/30 };
  289.         LONG    mod;
  290.  
  291.         drag_accum += imsg->MouseY;
  292.         mod = drag_accum / 10;
  293.         drag_accum -= mod * 10;
  294.  
  295.         current_time -= mod * scale[selected_digit];
  296.  
  297.         DrawTimeControl(TMData);
  298.         SetConductorState( control_player, CLOCKSTATE_SHUTTLE, current_time);
  299.     }
  300.     return (FALSE);
  301.  
  302. #if 0
  303.   if(eventfunc)
  304.     {
  305.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  306.     }
  307.   return(FALSE);
  308. #endif
  309.   }
  310.  
  311. BOOL Window_TRANSP_MOUSEUP(struct TMData *TMData, struct IntuiMessage *imsg)
  312.   {
  313.   TMOBJECTDATA *tmobjectdata;
  314.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  315.  
  316.     if (imsg->Code != SELECTUP)
  317.     {    last_gadget = NULL;
  318.         return FALSE;
  319.     }
  320.  
  321.     if (last_gadget == NULL) return FALSE;
  322.  
  323.   tmobjectdata = (TMOBJECTDATA *)(last_gadget->UserData);
  324.   eventfunc = tmobjectdata->EventFunc;
  325.  
  326.   if(eventfunc)
  327.     {
  328.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  329.     }
  330.   return(FALSE);
  331.   }
  332.  
  333. BOOL Window_TRANSP_INTUITICKS(struct TMData *TMData, struct IntuiMessage *imsg)
  334.   {
  335.  
  336.       if (drag_state)
  337.       {    if (drag_delay > 0) drag_delay--;
  338.           else
  339.           {    switch (drag_state) {
  340.               case DRAG_REW:
  341.                   if (GadgetInfo_REW.Gadget->Flags & SELECTED)
  342.                   {    current_time -= 600;
  343.                     DrawTimeControl(TMData);
  344.                     SetConductorState( control_player, CLOCKSTATE_SHUTTLE, current_time);
  345.                 }
  346.                 break;
  347.               case DRAG_FF:
  348.                   if (GadgetInfo_FF.Gadget->Flags & SELECTED)
  349.                   {    current_time += 600;
  350.                     DrawTimeControl(TMData);
  351.                     SetConductorState( control_player, CLOCKSTATE_SHUTTLE, current_time);
  352.                 }
  353.                 break;
  354.             }
  355.         }
  356.     }
  357.  
  358.  
  359.   return(FALSE);
  360.   }
  361.  
  362. BOOL Window_TRANSP_IDCMPUPDATE(struct TMData *TMData, struct IntuiMessage *imsg)
  363.   {
  364.   return(FALSE);
  365.   }
  366.  
  367. BOOL Window_SELECTCO_CLOSEWINDOW(struct TMData *TMData, struct IntuiMessage *imsg)
  368.   {
  369.   return(TRUE);
  370.   }
  371.  
  372. BOOL Window_SELECTCO_GADGETDOWN(struct TMData *TMData, struct IntuiMessage *imsg)
  373.   {
  374.   struct Gadget *gadget;
  375.   TMOBJECTDATA *tmobjectdata;
  376.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  377.  
  378.   gadget = (struct Gadget *)imsg->IAddress;
  379.   tmobjectdata = (TMOBJECTDATA *)(gadget->UserData);
  380.   eventfunc = tmobjectdata->EventFunc;
  381.  
  382.   if(eventfunc)
  383.     {
  384.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  385.     }
  386.   return(FALSE);
  387.   }
  388.  
  389. BOOL Window_SELECTCO_GADGETUP(struct TMData *TMData, struct IntuiMessage *imsg)
  390.   {
  391.   struct Gadget *gadget;
  392.   TMOBJECTDATA *tmobjectdata;
  393.   BOOL (*eventfunc)(struct TMData *, struct IntuiMessage *, TMOBJECTDATA *);
  394.  
  395.   gadget = (struct Gadget *)imsg->IAddress;
  396.   tmobjectdata = (TMOBJECTDATA *)(gadget->UserData);
  397.   eventfunc = tmobjectdata->EventFunc;
  398.  
  399.   if(eventfunc)
  400.     {
  401.     return((*eventfunc)(TMData, imsg, tmobjectdata));
  402.     }
  403.   return(FALSE);
  404.   }
  405.  
  406. /* ========================================================================= *
  407.    (My code....)
  408.  * ========================================================================= */
  409.  
  410. #if 0
  411.  
  412.     -- function needed:
  413.         -- refresh the window
  414.         -- draw the locator status
  415.         -- create list of conductors
  416.         -- maintain conductor name
  417.  
  418. #endif
  419.  
  420. UBYTE    time[4] = { 0,0,0,0};
  421. char    time_string[] = "  :  :  :  ";
  422. UBYTE    digit_index[8] = { 0,1,3,4,6,7,9,10 };
  423. BOOL    positive_only = TRUE;
  424. BOOL    wait_for_apps = TRUE;
  425.  
  426. void DrawCurrentTime(struct RastPort *rp, int selected)
  427. {    struct TextFont        *save_font = rp->Font;
  428.     BOOL                negative_time;
  429.     LONG                ctime,
  430.                         seconds,
  431.                         ticks;
  432.  
  433.         /* note that current time is is 600Hz ticks. We need to convert to 30 Hz */
  434.  
  435.     if (positive_only) current_time = MAX(0,current_time);
  436.  
  437.     ctime = clamp((-3600*9-60*59-59)*600,current_time,(3600*99+60*59+59)*600);
  438.  
  439.     if (ctime < 0) { ctime = -ctime; negative_time = TRUE; }
  440.     else negative_time = FALSE;
  441.  
  442.     seconds = ctime / 600;
  443.     ticks = (ctime - (seconds * 600));
  444.     ticks = ticks * 30 / 600;
  445.  
  446.     time[3] = ticks;
  447.     time[2] = seconds % 60;
  448.     time[1] = (seconds / 60) % 60;
  449.     time[0] = (seconds / 3600);
  450.  
  451.     time_string[0] = (time[0] / 10) + '0';
  452.     if (negative_time) time_string[0] = 59;
  453.     time_string[1] = (time[0] % 10) + '0';
  454.  
  455.     time_string[3] = (time[1] / 10) + '0';
  456.     time_string[4] = (time[1] % 10) + '0';
  457.  
  458.     time_string[6] = (time[2] / 10) + '0';
  459.     time_string[7] = (time[2] % 10) + '0';
  460.  
  461.     time_string[9] = (time[3] / 10) + '0';
  462.     time_string[10]= (time[3] % 10) + '0';
  463.  
  464.     SetFont(rp,&digitsFont);
  465.     SetAPen(rp,1);                    /* change to text pen... */
  466.     SetDrMd(rp,JAM2);                /* overwrite old digits */
  467.  
  468.         /* print one of the digits as highlighted */
  469.  
  470.     if (selected >= 0)
  471.     {    selected = digit_index[selected];
  472.  
  473.         Text(rp,time_string,selected);
  474.         SetAPen(rp,2);                    /* change to highlight text pen... */
  475.         Text(rp,time_string+selected,1);
  476.         SetAPen(rp,1);                    /* change to text pen... */
  477.         selected = 11 - selected - 1;
  478.         if (selected > 0) Text(rp,time_string+11-selected,selected);
  479.     }
  480.     else Text(rp,time_string,11);
  481.  
  482.     SetFont(rp,save_font);
  483. }
  484.  
  485. void DrawTimeControl(struct TMData *TMData)
  486. {    Move(    WindowInfo_TRANSP.Window->RPort,
  487.             GadgetInfo_CLOCK.Gadget->LeftEdge + 5,
  488.             GadgetInfo_CLOCK.Gadget->TopEdge + 14);
  489.  
  490.     DrawCurrentTime(WindowInfo_TRANSP.Window->RPort, selected_digit);
  491. }
  492.  
  493. extern struct Image clocklabel_im;
  494.  
  495. void RefreshWindow_TRANSP(struct TMData *TMData)
  496. {    DrawTimeControl(TMData);
  497.  
  498.         /* really need that DrawGlyph function... */
  499.  
  500.     DrawImage(    WindowInfo_TRANSP.Window->RPort,
  501.                 &clocklabel_im,
  502.                 GadgetInfo_CLOCK.Gadget->LeftEdge + 10,
  503.                 GadgetInfo_CLOCK.Gadget->TopEdge + 15);
  504. }
  505.  
  506.     /* REM: Move to y.lib? */
  507.  
  508. void SelectGadget(struct Window *w, struct Gadget *g, UWORD state)
  509. {    int pos;
  510.  
  511.     if ( (state && (g->Flags & SELECTED)) ||
  512.         !(state || (g->Flags & SELECTED)) ) return;
  513.  
  514.     pos = RemoveGList(w,g,1);
  515.     if (state) g->Flags |= SELECTED;
  516.     else g->Flags &= ~SELECTED;
  517.     RefreshGList(g,w,NULL,1);
  518.     AddGList(w,g,pos,1,NULL);
  519. }
  520.  
  521.  
  522. void SetGadgetStates(struct TMData *TMData)
  523. {
  524.     SelectGadget(WindowInfo_TRANSP.Window, GadgetInfo_PLAY.Gadget,
  525.         clock_state == CLOCKSTATE_RUNNING || clock_state == CLOCKSTATE_LOCATE );
  526.  
  527.     SelectGadget(WindowInfo_TRANSP.Window, GadgetInfo_STOP.Gadget,
  528.         clock_state == CLOCKSTATE_STOPPED );
  529.  
  530.     SelectGadget(WindowInfo_TRANSP.Window, GadgetInfo_PAUSE.Gadget,
  531.         clock_state == CLOCKSTATE_PAUSED );
  532. }
  533.  
  534. void PlayState(struct TMData *TMData)
  535. {
  536.         /* if clock not already running */
  537.  
  538.     if (clock_state != CLOCKSTATE_RUNNING && clock_state != CLOCKSTATE_LOCATE)
  539.     {        /* start the clock */
  540.  
  541.         SetConductorState(    control_player,
  542.                             wait_for_apps ? CLOCKSTATE_LOCATE : CLOCKSTATE_RUNNING,
  543.                             current_time);
  544.  
  545.             /* tell RealTime that we're done locating and are ready to get ticks */
  546.  
  547.         SetPlayerAttrs(control_player, PLAYER_Ready, TRUE, TAG_END);
  548.     }
  549.  
  550.     SetGadgetStates( TMData );
  551. }
  552.  
  553. void StopState(struct TMData *TMData)
  554. {
  555.     SetConductorState(control_player,CLOCKSTATE_STOPPED,0);
  556.  
  557.     SetGadgetStates( TMData );
  558. }
  559.  
  560. void PauseState(struct TMData *TMData)
  561. {
  562.     SetConductorState(control_player,CLOCKSTATE_PAUSED,0);
  563.  
  564.     SetGadgetStates( TMData );
  565. }
  566.  
  567. void HandleSignal(struct TMData *TMData, LONG signals)
  568. {
  569.     if (signals & SIGBREAKF_CTRL_E)
  570.     {    char            *status;
  571.  
  572.         clock_state = control_player->pi_Source->cdt_State;
  573.  
  574.         switch (clock_state) {
  575.         case CLOCKSTATE_STOPPED: status = "STOPPED"; break;
  576.         case CLOCKSTATE_PAUSED: status = "PAUSED"; break;
  577.         case CLOCKSTATE_LOCATE:
  578.             SetPlayerAttrs(control_player, PLAYER_Ready, TRUE, TAG_END);
  579.             status = "LOCATING";
  580.             break;
  581.         case CLOCKSTATE_RUNNING: status = "RUNNING"; break;
  582.         default: status = "UNKNOWN";
  583.         }
  584.  
  585.         DrawTimeControl(TMData);
  586.  
  587.         GT_SetGadgetAttrs(GadgetInfo_STATUS.Gadget, WindowInfo_TRANSP.Window, NULL,
  588.             GTTX_Text, status, TAG_DONE );
  589.  
  590.         SetGadgetStates( TMData );
  591.     }
  592.  
  593.     if (signals & SIGBREAKF_CTRL_F /* && clock_state == CLOCKSTATE_RUNNING */ )
  594.     {
  595.         DrawTimeControl(TMData);
  596.     }
  597. }
  598.  
  599. struct CondEntry {
  600.     struct Node            node;
  601.     char                name[ 32 ];
  602. };
  603.  
  604.     /* REM: Move to new library... */
  605.  
  606. WORD AlphaInsertNode(struct List *l, struct Node *n)
  607. {    struct Node            *search;
  608.     WORD                pos = 0;
  609.  
  610.     for (    search=l->lh_Head ;                /* insert alphabetically        */
  611.             search->ln_Succ ;
  612.             search=search->ln_Succ, pos++ )
  613.     {    if (Stricmp(search->ln_Name,n->ln_Name) >= 0) break;
  614.     }
  615.     Insert(l,n,search->ln_Pred);
  616.     return pos;
  617. }
  618.  
  619. void FreeConductorList( struct List *list )
  620. {    struct CondEntry    *ce;
  621.  
  622.     while (ce = (struct CondEntry *)RemHead( list ) )
  623.         FreeMem( ce, sizeof *ce );
  624. }
  625.  
  626. void GetConductorList( struct List *list )
  627. {    struct Conductor    *cond;
  628.  
  629.     NewList( list );
  630.  
  631.     for (cond = NextConductor( NULL ); cond; cond = NextConductor ( cond ) )
  632.     {    struct CondEntry *ce;
  633.  
  634.         if ( ce = AllocMem( sizeof *ce, MEMF_CLEAR ))
  635.         {    strncpy( ce->name, cond->cdt_Node.ln_Name, sizeof ce->name );
  636.             ce->node.ln_Name = ce->name;
  637.             AlphaInsertNode( list, &ce->node );
  638.         }
  639.     }
  640. }
  641.  
  642. void ShowConductorName(struct TMData *TMData)
  643. {    GT_SetGadgetAttrs(GadgetInfo_NEWCON.Gadget, WindowInfo_SELECTCO.Window, NULL,
  644.         GTST_String, control_player->pi_Source->cdt_Node.ln_Name, TAG_DONE );
  645. }
  646.  
  647. void NewConductorName( char *newname )
  648. {    SetPlayerAttrs(control_player, PLAYER_Conductor, newname, TAG_END);
  649. }
  650.  
  651.     /* Hook function... */
  652.  
  653. ULONG __asm __interrupt __saveds myHookFunc (
  654.     register __a1 struct pmTime        *msg,
  655.     register __a2 struct PlayerInfo *pi )
  656. {    struct Conductor *cond = pi->pi_Source;
  657.     static LONG last_time;
  658.  
  659.     switch (msg->pmt_Method) {
  660.     case PM_TICK:
  661.         current_time = msg->pmt_Time;
  662.         if ( (current_time ^ last_time) & ~0x3f)
  663.         {    Signal(main_task,SIGBREAKF_CTRL_F);
  664.             last_time = current_time;
  665.         }
  666.         break;
  667.     case PM_STATE:
  668.         clock_state = cond->cdt_State;
  669.         Signal(main_task,SIGBREAKF_CTRL_E);
  670.         break;
  671.  
  672.     case PM_SHUTTLE:
  673.         current_time = msg->pmt_Time;
  674.         if ( (current_time ^ last_time) & ~0x3f)
  675.         {    Signal(main_task,SIGBREAKF_CTRL_F);
  676.             last_time = current_time;
  677.         }
  678.     }
  679.     return 0L;
  680. }
  681.